﻿namespace Nomo.UnityCoreModule
{
    /// <summary>
    /// 选项卡。
    /// </summary>
    [UnityEngine.DisallowMultipleComponent]
    [UnityEngine.SelectionBase]
    [UnityEngine.RequireComponent(typeof(UnityEngine.RectTransform))]
    public sealed class Tab : UnityEngine.EventSystems.UIBehaviour, UnityEngine.EventSystems.IPointerClickHandler
    {
        /// <summary>
        /// 可交互吗？
        /// </summary>
        public bool interactable = true;

        [UnityEngine.SerializeField] private bool     isOn;
        [UnityEngine.SerializeField] private TabGroup tabGroup;

        /// <summary>
        /// 这些物体会在 <see cref="IsOn"/> 为 <see langword="false"/> 时激活，为 <see langword="true"/> 时取消激活。
        /// </summary>
        public UnityEngine.GameObject[] offs;

        /// <summary>
        /// 这些物体会在 <see cref="IsOn"/> 为 <see langword="true"/> 时激活，为 <see langword="false"/> 时取消激活。
        /// </summary>
        public UnityEngine.GameObject[] ons;

        /// <summary>
        /// <see cref="IsOn"/> 的值发生变化。
        /// </summary>
        public event System.Action<bool> ValueChanged;

        /// <summary>
        /// 是否处于开启状态？
        /// </summary>
        public bool IsOn { get => isOn; set => SetIsOn(value); }

        /// <summary>
        /// 选项卡组。
        /// </summary>
        public TabGroup TabGroup
        {
            get => tabGroup;
            set
            {
                SetTabGroup(value, true);
                DoStateTransition();
            }
        }

        private void DoStateTransition()
        {
            if (offs != null)
            {
                foreach (var element in offs)
                {
                    if (element != null)
                    {
                        element.SetActive(!isOn);
                    }
                }
            }
            if (ons != null)
            {
                foreach (var element in ons)
                {
                    if (element != null)
                    {
                        element.SetActive(isOn);
                    }
                }
            }
        }

        private void SetIsOn(bool value)
        {
            if (isOn == value)
            {
                return;
            }

            isOn = value;
            if (tabGroup != null && IsActive() && (isOn || !tabGroup.AnyTabsOn()))
            {
                isOn = true;
                tabGroup.NotifyTabOn(this);
            }

            DoStateTransition();
            ValueChanged?.Invoke(isOn);
        }

        private void InternalTab()
        {
            if (IsActive() && interactable)
            {
                IsOn = !IsOn;
            }
        }

        private void SetTabGroup(TabGroup newGroup, bool setMemberValue)
        {
            if (tabGroup != null)
            {
                tabGroup.UnregisterTab(this);
            }
            if (setMemberValue)
            {
                tabGroup = newGroup;
            }
            if (newGroup != null && IsActive())
            {
                newGroup.RegisterTab(this);
                if (isOn)
                {
                    newGroup.NotifyTabOn(this);
                }
            }
        }

        void UnityEngine.EventSystems.IPointerClickHandler.OnPointerClick(UnityEngine.EventSystems.PointerEventData eventData)
        {
            if (!interactable)
            {
                return;
            }

            if (eventData.button != UnityEngine.EventSystems.PointerEventData.InputButton.Left)
            {
                return;
            }

            InternalTab();
        }

        /// <inheritdoc />
        protected override void OnEnable()
        {
            base.OnEnable();
            SetTabGroup(tabGroup, false);
            DoStateTransition();
        }

        /// <inheritdoc />
        protected override void OnDisable()
        {
            SetTabGroup(null, false);
            base.OnDisable();
        }

        /// <inheritdoc />
        protected override void OnDestroy()
        {
            if (tabGroup != null)
            {
                tabGroup.EnsureValidState();
            }
            base.OnDestroy();
        }
    }
}
